package com.gss.system.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.gss.common.core.service.BaseServiceImpl;
import com.gss.datasource.mapper.sys.*;
import com.gss.entity.R;
import com.gss.entity.enums.ConstantEnum;
import com.gss.entity.sys.dto.*;
import com.gss.entity.sys.vo.SysDeptRoleVo;
import com.gss.entity.sys.vo.SysMenuVo;
import com.gss.entity.sys.vo.SysUserDeptVo;
import com.gss.plugin.oauth2.exception.CustomAuthException;
import com.gss.system.service.ISysUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author DYang
 * @date 2023/6/17
 */
@Slf4j
@Service("sysUserService")
public class SysUserServiceImpl extends BaseServiceImpl<SysUser> implements ISysUserService  {

    @Autowired
    private SysMenuMapper menuMapper;
    @Autowired
    private SysRoleMapper roleMapper;
    @Autowired
    private SysDeptMapper deptMapper;
    @Autowired
    private SysUserDeptMapper userDeptMapper;


    @Override
    public boolean save(SysUser entity) {
        //设置密码
        String encode = new BCryptPasswordEncoder().encode(entity.getPassword());
        entity.setPassword(encode);
        return super.save(entity);
    }

    @Override
    public SysUser getUserByName(String userName) {
        SysUser sysUser = null;
        try {
            // 判断用户名是否重复
            QueryWrapper<SysUser> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("user_name",userName);
            sysUser = this.getOne(queryWrapper);
        } catch (Exception e) {
            log.error("【用户管理】 根据用户名查询失败 ",e);
            throw e;
        }
        return sysUser;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public R<String> oauthDeptRole(SysUserDeptVo entity) {
        Integer userId = entity.getId();
        List<SysDeptRoleVo> deptList = entity.getDeptVoList();
        if (userId == null || CollUtil.isEmpty(deptList)) {
            return R.error(ConstantEnum.PARAM_ERROR);
        }

        for (SysDeptRoleVo roleVo : deptList) {
            SysUserDept userDept = new SysUserDept();
            userDept.setUserId(userId);
            userDept.setDeptId(roleVo.getId());
            userDept.setEnable(0);
            userDept.setCreateTime(new Date());

            userDeptMapper.insert(userDept);
        }
        return R.ok("操作成功");
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public R<String> deleteDeptRole(List<Integer> idList) {
        int deleted = userDeptMapper.deleteBatchIds(idList);
        return deleted > 0 ? R.ok("操作成功") : R.error(ConstantEnum.DEL_ERROR);
    }

    @Override
    public R<SysUserDeptVo> userInfo(String username) {
        // 用户信息
        QueryWrapper<SysUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_name", username).or().eq("email",username);
        SysUser user = this.getOne(queryWrapper);
        if (user == null) {
            return null;
        }
        user.setPassword(null);
        SysUserDeptVo userVo = new SysUserDeptVo();
        BeanUtils.copyProperties(user,userVo);
        List<SysMenu> menuList = null;
        if ("super".equals(username)) {
            // 拥有的权限
            QueryWrapper<SysMenu> wrapper = new QueryWrapper<>();
            menuList = menuMapper.selectList(wrapper);
        }else {
            // 所属部门
            List<SysDept> deptList = deptMapper.getDeptEnableListByUserId(user.getId());
            if (CollUtil.isEmpty(deptList)) {
                return R.ok(userVo);
            }
            userVo.setDeptList(deptList);
            // 拥有角色
            List<Integer> deptIdList = deptList.stream().map(SysDept::getId).collect(Collectors.toList());
            List<SysRole> roleList = roleMapper.listRoleEnableByDeptId(deptIdList);
            if (ObjectUtil.isEmpty(roleList)) {
                return R.ok(userVo);
            }
            userVo.setRoleList(roleList);
            // 拥有的权限
            List<Integer> roleIdList = roleList.stream().map(SysRole::getId).collect(Collectors.toList());
            menuList = menuMapper.listMenuEnableByRoleId(roleIdList);
            if (CollUtil.isEmpty(menuList)) {
                return R.ok(userVo);
            }
        }
        if (!CollUtil.isEmpty(menuList)) {
            List<SysMenuVo> resourceList = this.buildMenuResource(menuList);
            userVo.setResourceList(resourceList);
        }
        return R.ok(userVo);
    }

    @Override
    public List<SysMenuVo> permissionRoutes(String roles) {
        List<SysMenu> list = null;
        if(roles.contains("super")) {
            QueryWrapper<SysMenu> queryWrapper = new QueryWrapper<>();
            queryWrapper.orderByAsc("id");
            list = menuMapper.selectList(queryWrapper);
        }else {
            List<String> roleList = Arrays.asList(roles.split(","));
            list = menuMapper.listMenuEnableByRoleCode(roleList);
            if (CollUtil.isEmpty(list)) {
                return new ArrayList<>();
            }
        }

        return this.buildMenuResource(list);
    }

    /**
     * 构建菜单资源
     * @param list
     * @return
     */
    private List<SysMenuVo> buildMenuResource(List<SysMenu> list) {
        // 菜单分组
        List<SysMenuVo> groupList = list.stream().filter(x -> !x.getRoute().contains(":") && x.getMenuType() == 0)
                .map(x -> {
                    SysMenuVo menuVo = new SysMenuVo();
                    BeanUtils.copyProperties(x, menuVo);
                    return menuVo;
                }).collect(Collectors.toList());
        // 获取子集菜单
        for (SysMenuVo menuVo : groupList) {
            String route = menuVo.getRoute();
            List<SysMenuVo> child = this.groupMenu(1,route,list);
            if (CollUtil.isNotEmpty(child)) {
                menuVo.setChild(child);
            }
        }
        return groupList;
    }

    /**
     * 对子集进行分组
     * @param deep  深度
     * @param parentRoute
     * @param list
     * @return
     */
    private List<SysMenuVo> groupMenu(int deep,String parentRoute, List<SysMenu> list) {
        int finalDeep = deep;
        List<SysMenuVo> groupList = list.stream()
                .filter(x -> x.getRoute().startsWith(parentRoute) && StrUtil.count(x.getRoute(), ":") == finalDeep)
                .map(x -> {
                    SysMenuVo menuVo = new SysMenuVo();
                    BeanUtils.copyProperties(x, menuVo);
                    return menuVo;
                }).collect(Collectors.toList());

        for (SysMenuVo menuVo : groupList) {
            String route = menuVo.getRoute();
            List<SysMenuVo> child = this.groupMenu(++deep, route, list);
            if (CollUtil.isNotEmpty(child)) {
                menuVo.setChild(child);
            }
        }
        return groupList;
    }


}
